package com.bjut.config;

import cn.hutool.core.util.ObjectUtil;
import com.bjut.constant.AuthConstants;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * feign拦截器
 *  作用：解决服务之间调用没有token的情况
 *
 *  浏览器 -> A服务 -> B服务 (此时B服务没有所需要的token,需要A把token想B传递，这样A就可以继续调用B服务)
 *  定时器 -> A服务
 */
@Component
public class FeignInterceptor implements RequestInterceptor {

    /**
     * A 调用 B服务的时候用的是以下对象，为什么？？？
     * @param requestTemplate
     */
    @Override
    public void apply(RequestTemplate requestTemplate) {
        // 获取当前请求的上下文对象
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        // 判断是否有值
        if (ObjectUtil.isNotNull(requestAttributes)) {
            // 获取请求对象
            HttpServletRequest request = requestAttributes.getRequest();
            // 判断是否有值
            if (ObjectUtil.isNotNull(request)) {
                // 获取当前请求头中的token值，传递到一下一个请求对象的请求头中
                String authorization = request.getHeader(AuthConstants.AUTHORIZATION);
                /**
                 * requestTemplate.header(...) 不是触发调用的代码，
                 * 而是 给将要通过 Feign 发起的请求“加请求头”。
                 * Feign 框架会在稍后自动执行这个 HTTP 调用，
                 * 而 RequestInterceptor 就是专门用于**“在发请求之前修改请求内容”**的。
                 */
                /**
                 * 什么是 FeignInterceptor？
                 * 它实现了 RequestInterceptor 接口；
                 *
                 * 是 Feign 提供的请求前处理机制；
                 *
                 * 当你的代码中使用了 @FeignClient 去调用别的服务时，Feign 会在请求发出前，自动执行这个拦截器的 apply() 方法；
                 *
                 * 你在 apply() 里设置的内容（如请求头、参数等）就会加到这个请求中。
                 */
                requestTemplate.header(AuthConstants.AUTHORIZATION,authorization);
                return;
            }
        }
        /**
         * 一路从浏览器请求过来的请求肯定是含有TOKEN的，但是有些请求不是从浏览器一路过来的，
         * 比如：定时器 -> A服务，这时的请求是没有携带认证TOKEN的，所有这里我需要为这些请求添加一个固定的TOKEN。
         * 从而跳过需要Security认证的困扰；
         */
        requestTemplate.header(AuthConstants.AUTHORIZATION,AuthConstants.BEARER+"e26e61de-4418-4ebd-9148-2e27a189c9d5");

    }
}
